import argparse
import os

from ansible.cli.playbook import PlaybookCLI
from ansible.executor.playbook_executor import PlaybookExecutor
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.inventory.group import Group
from ansible.inventory.host import Host
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.playbook import Play
from ansible.plugins.loader import action_loader
from ansible.utils.context_objects import CLIArgs
from ansible.vars.manager import VariableManager
from django.contrib import admin, messages
from django.forms import forms
import ansible.constants as C
from django.conf import settings

from .models import ECS
from .client import aliyunEcsAdmin
import string
import secrets
from ansible import context



# Register your models here.

class ECSAdmin(admin.ModelAdmin):
    actions = ["createServer", "updateServer", "inviteServer", "checkServer", "deleteServer", "baseline"]
    list_display = [f.name for f in ECS._meta.fields]

    # def clean(self):
    #     # 这里可以选择不进行任何强制验证，从而允许所有字段为空
    #     pass

    @staticmethod
    def generateInitialPassword():
        alphabet = string.ascii_letters + string.digits
        while True:
            password = ''.join(secrets.choice(alphabet) for i in range(10))
            if (any(c.islower() for c in password)
                    and any(c.isupper() for c in password)
                    and sum(c.isdigit() for c in password) >= 3):
                break
        return password

    @admin.action(description="Delete Server")
    def deleteServer(self, request, queryset):

        instanceIds = [ecs.instanceId for ecs in queryset]
        aliyunEcsAdmin.delete(instanceIds)

        #只有创建完了才允许删除，所以要失败时不能删除，后续增加逻辑
        [ecs.delete() for ecs in queryset]

    @admin.action(description="Create Server")
    def createServer(self, request, queryset):

        initialPassword = ECSAdmin.generateInitialPassword()

        hostnames = [ecs.hostname for ecs in queryset]
        instanceIds = aliyunEcsAdmin.create(hostnames, initialPassword=initialPassword)

        for ecs, instanceId in zip(queryset, instanceIds):
            ecs.instanceId = instanceId
            ecs.initialPassword = initialPassword
            ecs.save()
            self.message_user(
                request,
                "{0}\t{1}".format(ecs.instanceId, ecs.hostname),
                messages.SUCCESS,
            )

    @admin.action(description="Update Server")
    def updateServer(self, request, queryset):
        #instanceIds = [ecs.instanceId for ecs in queryset]
        for ecs in queryset:
            instances = aliyunEcsAdmin.select([ecs.instanceId])
            print(instances)
            ecs.host = instances[0].public_ip_address.ip_address[0]
            ecs.save()

    @admin.action(description="Invite Server")
    def inviteServer(self, request, queryset):

        for ecs in queryset:
            print(ecs.instanceId)
            print(ecs.hostname)
            print(ecs.host)
            # messages.add_message(request, messages.INFO, ecs.instanceId)

            dl = DataLoader()
            im = InventoryManager(loader=dl)
            vm = VariableManager(loader=dl, inventory=im)

            im.add_host(ecs.instanceId, 'all')

            host = im.get_host(ecs.instanceId)
            host.vars['ansible_user'] = 'root'
            host.vars['ansible_host'] = ecs.host
            host.vars['ansible_ssh_extra_args'] = '-o StrictHostKeyChecking=no'



            print(vm.get_vars(host=host))


            # allGroups = im.get_groups_dict()
            # print(allGroups)

            public_key_path = os.path.expanduser('~/.ssh/id_rsa.pub')
            if os.path.exists(public_key_path):
                public_key = open(public_key_path).read().strip()

            play_source = dict(
                name="Add SSH Key",
                hosts='all',
                connection="ssh",
                gather_facts='no',
                tasks=[
                    dict(
                        action=dict(
                            module='authorized_key',
                            args=dict(
                                key=public_key,
                                state='present',
                                user='root'
                            )
                        )
                    )
                ]
            )

            passwords = {}
            password = ecs.initialPassword
            while not password:
                password = input("Enter the password for the remote hosts: ")
            passwords["conn_pass"] = password

            # play_source = {
            #     "name": "Ansible Play",  # 任务名称
            #     "hosts": "localhost",  # 目标主机，可以填写具体主机也可以是主机组名称
            #     "gather_facts": "no",  # 是否收集配置信息
            #     # tasks是具体执行的任务，列表形式，每个具体任务都是一个字典
            #     "tasks": [
            #         {
            #             "action": {
            #                 "module": "shell",
            #                 "args": "hostname",
            #                 "warn": False
            #             }
            #         }
            #     ]
            # }

            play = Play().load(play_source, variable_manager=vm, loader=dl)

            tqm = TaskQueueManager(
                inventory=im,
                variable_manager=vm,
                loader=dl,
                passwords=passwords
            )

            result = tqm.run(play)

            tqm.cleanup()
            dl.cleanup_all_tmp_files()

    @admin.action(description="Baseline")
    def baseline(self, request, queryset):

        ANSIBLE_CFG_PATH = os.path.join(settings.BASE_DIR, '.gitRepoHub/autoble/example/k8s/ansible.cfg')
        # 设置Playbook路径
        PLAYBOOK_PATH = '.gitRepoHub/autoble/example/k8s/playbooks/01.baseline.yaml'
        # 设置角色路径
        ROLE_PATHS = ['.gitRepoHub/autoble/example/k8s/steps', '.gitRepoHub/autoble/example/k8s/roles']


        dl = DataLoader()
        im = InventoryManager(loader=dl, sources=os.path.join(settings.BASE_DIR, '.gitRepoHub/autoble/example/k8s/inventories'))
        # im = InventoryManager(loader=loader, sources=['/etc/ansible/hosts'])

        for ecs in queryset:
            im.add_host(ecs.instanceId, 'all')
            host = im.get_host(ecs.instanceId)
            host.vars['ansible_user'] = 'root'
            host.vars['ansible_host'] = ecs.host
            host.vars['ansible_roles_path'] = ":".join(ROLE_PATHS)

        vm = VariableManager(loader=dl, inventory=im)
        vm.extra_vars.update({
            "ANSIBLE_CONFIG": ANSIBLE_CFG_PATH,
            "ANSIBLE_ROLES_PATH": ROLE_PATHS
        })

        print(vm.get_vars())

        # play_source =  {
        #     "name": "My Play",
        #     "hosts": "all",
        #     "gather_facts": "yes",
        #     "tasks": [
        #         {
        #             "name": "Execute roleX task that references roleY",
        #             "import_role": {
        #                 "name": "baseline",
        #                 "tasks_from": os.path.join(settings.BASE_DIR, ".gitRepoHub/autoble/example/k8s/steps/baseline/tasks/main.yaml"),
        #             }
        #         }
        #     ]
        # }
        play_source = {
            "name": "My Play",
            "hosts": "all",
            "connection": "ssh",
            "gather_facts": "yes",
            "roles": [
                {
                    "role": os.path.join(settings.BASE_DIR, ".gitRepoHub/autoble/example/k8s/steps/baseline"),
                }
            ]
        }

        play = Play().load(play_source, variable_manager=vm, loader=dl)



        tqm = TaskQueueManager(
            inventory=im,
            variable_manager=vm,
            loader=dl,
            passwords={}
        )

        result = tqm.run(play)


        print(result)


admin.site.register(ECS, ECSAdmin)
